package com.yhy.wxzn.wcs;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yhy.wxzn.common.enums.WcsDeviceTypeEnums;
import com.yhy.wxzn.common.utils.SpringUtil;
import com.yhy.wxzn.common.utils.WcsUtils;
import com.yhy.wxzn.wcs.device.plc.bean.*;
import com.yhy.wxzn.wcs.device.plc.siemens.SiemensPlcServer;
import com.yhy.wxzn.wcs.device.plc.task.InPortTaskThread;
import com.yhy.wxzn.wcs.device.plc.xj.XjPlcDriver;
import com.yhy.wxzn.wcs.device.plc.xj.XjPlcServer;
import com.yhy.wxzn.wcs.device.rgv.FourWayRgvTaskExecuteThread;
import com.yhy.wxzn.wcs.device.rgv.bean.Coord;
import com.yhy.wxzn.wcs.device.rgv.bean.Lifter;
import com.yhy.wxzn.wcs.device.rgv.bean.Node;
import com.yhy.wxzn.wcs.device.rgv.core.avoid.AvoidCentralManagerThread;
import com.yhy.wxzn.wcs.device.rgv.core.lock.LockNodeManager;
import com.yhy.wxzn.wcs.device.rgv.RgvTaskAssignManagerThread;
import com.yhy.wxzn.wcs.device.rgv.bean.FourWayRgv;
import com.yhy.wxzn.wcs.device.scanner.BarcodeScannerClient;
import com.yhy.wxzn.wcs.device.scanner.bean.IpAddress;
import com.yhy.wxzn.wcs.entity.*;
import com.yhy.wxzn.wcs.enums.PortModel;
import com.yhy.wxzn.wcs.service.IWcsPlcConfigService;
import com.yhy.wxzn.wcs.service.IWcsPlcPropertyService;
import com.yhy.wxzn.wcs.service.impl.WcsDeviceInfoServiceImpl;
import com.yhy.wxzn.wcs.service.impl.WcsMapInfoServiceImpl;
import com.yhy.wxzn.wcs.service.impl.WcsPlcPropertyServiceImpl;
import com.yhy.wxzn.wcs.service.impl.WcsPortServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


@Slf4j
@Component
@RequiredArgsConstructor
@DependsOn({"springUtil"})
public class SystemInit {

    public static final boolean Local_Test = false;
    public static final boolean Lifter_Connection= true;


    public static final List<FourWayRgv> fourWayRgvs = new ArrayList<>();
    public static final Map<Integer,FourWayRgv> fourWayRgvMap = new HashMap<>();

    public static final List<Integer> plcRgvIds = new ArrayList<>();
    public static final Map<Integer, FourCarPlc> rgvPlcMap = new HashMap<>();
    public static final Map<Integer, XjPlcDriver> rgvDriverMap = new HashMap<>();

    public static final Map<Integer, XJPHoistPlc> liferPlcMap = new HashMap<>();
    public static final Map<Integer, XjPlcDriver> liferDriverMap = new HashMap<>();
    public static final Map<Lifter, Integer> liferToDeviceIdMap = new HashMap<>();

    public static final Map<Integer, XjPlcDriver> transmissionDriverMap = new HashMap<>();


    public static final Map<Lifter, HoistPlc> liferToHoistPlcMap = new HashMap<>();
    public static final Map<Coord, TransmissionPlc> coordToTransmissionPlcMap = new HashMap<>();


    public static final Map<String, BasePlc> nameToBasePlc = new HashMap<>();





    final WcsDeviceInfoServiceImpl wcsDeviceInfoService;

    final WcsPlcPropertyServiceImpl wcsPlcPropertyService;

    final IWcsPlcConfigService plcConfigService;

    final IWcsPlcPropertyService plcPropertyService;

    final WcsMapInfoServiceImpl wcsMapInfoService;

    final WcsPortServiceImpl portService;


    @PostConstruct
    void init(){
        //初始化PLC信息
        initPlc();
        initPort();
        initRgv();
    }

    private void initPort() {
        List<DeviceNetworkInfo> scannerNetworkInfos = wcsDeviceInfoService.findDeviceNetworkInfoByDeviceType(WcsDeviceTypeEnums.BCR.getValue());
        scannerNetworkInfos.forEach( deviceNetworkInfo -> new BarcodeScannerClient(deviceNetworkInfo).start());

        List<WcsPort> collect = portService.list().stream().filter(port -> port.getPortMode().equals(PortModel.IN_PORT) || port.getPortMode().equals(PortModel.IN_AND_OUT)).collect(Collectors.toList());
        collect.forEach(port -> new InPortTaskThread(port).start());
    }

    private void initPlc() {
        //获取Plc配置信息
        List<WcsPlcConfig> plcConfigList = plcConfigService.list();
        if(CollectionUtils.isEmpty(plcConfigList)){
            return;
        }
        for (WcsPlcConfig plc:plcConfigList) {
            //获取PLC配置表根据设备分组
            LambdaQueryWrapper<WcsPlcProperty> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WcsPlcProperty::getPlcId,plc.getId());
            List<WcsPlcProperty> plcProperties = plcPropertyService.list(queryWrapper);
            if(CollectionUtils.isEmpty(plcProperties)){
                continue;
            }
            Map<Integer,List<WcsPlcProperty>> propertyMap = plcProperties.stream().collect(Collectors.groupingBy(WcsPlcProperty::getDeviceId));
            /**
             * 1.1:获取PLC型号，不同的型号初始化不同的PLC服务
             * 1.2:PLC类型字典配置1-西门子,2-信捷,3-三菱，4-欧姆龙
             * */
            String plcType = plc.getType();
            switch (plcType){
                case "1":
                    SiemensPlcServer siemensPlcServer = new SiemensPlcServer();
                    siemensPlcServer.initProtocol(plc,propertyMap);
                    break;
                case "2":
                    XjPlcServer xjPlcServer = new XjPlcServer();
                    xjPlcServer.initProtocol(plc,propertyMap);
                    break;
                default:
                    break;
            }
        }
    }


    private void initRgv() {

        plcRgvIds.forEach(id-> initRgv(id));

        //小车任务分配线程
        new RgvTaskAssignManagerThread().start();

        new AvoidCentralManagerThread().start();

        fourWayRgvs.forEach(fourWayRgv -> fourWayRgv.getFourWayRgvExecuteTaskThread().start());
    }

    private void initRgv(Integer id) {
        WcsDeviceInfo rgvInfo = wcsDeviceInfoService.getById(id);

        FourWayRgv fourWayRgv = new FourWayRgv();

        fourWayRgv.setDeviceInfo(rgvInfo);

        fourWayRgv.setFourCarPlc(rgvPlcMap.get(id));

        fourWayRgv.setXjPlcDriver(rgvDriverMap.get(id));

        FourWayRgvTaskExecuteThread fourWayRgvExecuteTaskThread = new FourWayRgvTaskExecuteThread(fourWayRgv);

        fourWayRgv.setFourWayRgvExecuteTaskThread(fourWayRgvExecuteTaskThread);

        fourWayRgvs.add(fourWayRgv);
        fourWayRgvMap.put(rgvInfo.getId(),fourWayRgv);

        String twoCode = rgvPlcMap.get(id).getTwoCode();
        //todo 上线去掉注释
//        if(StrUtil.isEmpty(twoCode) || ! Objects.equals(Node.parseNode(rgvInfo.getLocation()),fourWayRgv.getCurLocation(twoCode))){
//            throw new RuntimeException("小车id："+id+"，未扫到地码或当前位置与数据库中暂存位置不一致");
//        }

        //锁定小车当前位置
        LockNodeManager.insertLocationLock(fourWayRgv, wcsMapInfoService.getNode(Node.parseNode(rgvInfo.getLocation())));
    }
}
